<template>
  <div class="ai-chat-container">

    <div class="chat-body" ref="chatBodyRef">
      <div v-if="messages.length === 0" class="empty-state">
        <div class="empty-icon">💬</div>
        <h3>开始与AI对话</h3>
        <p>问我任何关于英语学习的问题，我会尽力帮助您！</p>
        <div class="suggestions">
          <div 
            v-for="(suggestion, index) in suggestions" 
            :key="index"
            class="suggestion-item"
            @click="sendMessage(suggestion)"
          >
            {{ suggestion }}
          </div>
        </div>
      </div>

      <div v-else class="messages-list">
        <div 
          v-for="(message, index) in messages" 
          :key="index"
          :class="['message-item', message.role]"
        >
          <div class="message-avatar">
            <img 
              v-if="message.role === 'user'" 
              :src="userStore.userInfo.avatarUrl || avatarDefault" 
              :alt="userStore.userInfo.username || '用户'"
              class="user-avatar"
            />
            <div v-else class="ai-avatar-small">
              <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M12 2L2 7L12 12L22 7L12 2Z" fill="currentColor"/>
                <path d="M2 17L12 22L22 17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                <path d="M2 12L12 17L22 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
              </svg>
            </div>
          </div>
          <div class="message-content">
            <!-- 编辑模式 -->
            <div v-if="message.role === 'user' && editingMessageIndex === index" class="message-edit-wrapper">
              <el-input
                v-model="editingContent"
                type="textarea"
                :autosize="{ minRows: 2, maxRows: 6 }"
                class="message-edit-input"
                @keydown.ctrl.enter.exact.prevent="handleSaveEdit(index)"
                @keydown.esc.exact.prevent="handleCancelEdit"
              />
              <div class="edit-actions">
                <button class="edit-save-btn" @click="handleSaveEdit(index)">
                  <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                    <path d="M9 16.17L4.83 12L3.41 13.41L9 19L21 7L19.59 5.59L9 16.17Z" fill="currentColor"/>
                  </svg>
                  <span>发送</span>
                </button>
                <button class="edit-cancel-btn" @click="handleCancelEdit">
                  <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                    <path d="M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12L19 6.41Z" fill="currentColor"/>
                  </svg>
                  <span>取消</span>
                </button>
              </div>
            </div>
            <!-- 正常显示模式 -->
            <div v-else>
              <div 
                v-if="message.content" 
                class="message-text-wrapper"
                @mouseenter="handleMessageHover(index)"
                @mouseleave="handleMessageLeave"
              >
                <div class="message-text" v-html="formatMessage(message.content)"></div>
                <!-- AI消息的复制按钮（保留原有功能） -->
                <button 
                  v-if="message.role === 'assistant' && hoveredMessageIndex === index && !message.isStreaming"
                  class="copy-button"
                  @click.stop="copyMessage(message.content, index)"
                  :title="copiedIndex === index ? '已复制' : '复制消息'"
                >
                  <svg v-if="copiedIndex !== index" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                    <path d="M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1ZM19 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H19C20.1 23 21 22.1 21 21V7C21 5.9 20.1 5 19 5ZM19 21H8V7H19V21Z" fill="currentColor"/>
                  </svg>
                  <svg v-else viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                    <path d="M9 16.17L4.83 12L3.41 13.41L9 19L21 7L19.59 5.59L9 16.17Z" fill="currentColor"/>
                  </svg>
                </button>
              </div>
              <div v-if="message.role === 'assistant' && message.isStreaming" class="typing-indicator">
                <span></span><span></span><span></span>
              </div>
            </div>
            <!-- 用户消息的操作按钮（显示在消息框外部） -->
            <div 
              v-if="message.role === 'user' && hoveredMessageIndex === index && !isLoading && editingMessageIndex !== index"
              class="message-actions"
              @mouseenter="handleActionsHover"
              @mouseleave="handleActionsLeave"
            >
              <button 
                class="action-btn copy-btn"
                @click.stop="copyMessage(message.content, index)"
                :title="copiedIndex === index ? '已复制' : '复制消息'"
              >
                <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                  <path v-if="copiedIndex !== index" d="M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1ZM19 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H19C20.1 23 21 22.1 21 21V7C21 5.9 20.1 5 19 5ZM19 21H8V7H19V21Z" fill="currentColor"/>
                  <path v-else d="M9 16.17L4.83 12L3.41 13.41L9 19L21 7L19.59 5.59L9 16.17Z" fill="currentColor"/>
                </svg>
              </button>
              <button 
                class="action-btn edit-btn"
                @click.stop="handleStartEdit(message, index)"
                title="编辑消息"
              >
                <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                  <path d="M3 17.25V21H6.75L17.81 9.94L14.06 6.19L3 17.25ZM20.71 7.04C21.1 6.65 21.1 6.02 20.71 5.63L18.37 3.29C17.98 2.9 17.35 2.9 16.96 3.29L15.12 5.12L18.87 8.87L20.71 7.04Z" fill="currentColor"/>
                </svg>
              </button>
              <button 
                class="action-btn delete-btn"
                @click.stop="handleDeleteMessage(message, index)"
                title="删除消息"
              >
                <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                  <path d="M6 19C6 20.1 6.9 21 8 21H16C17.1 21 18 20.1 18 19V7H6V19ZM19 4H15.5L14.5 3H9.5L8.5 4H5V6H19V4Z" fill="currentColor"/>
                </svg>
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>

    <div class="chat-bottom">
      <div class="bottom-wrapper">

        <div class="bottom-row">
          <div class="chat-bottom-left">
            <div class="ai-avatar">
              <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M12 2L2 7L12 12L22 7L12 2Z" fill="currentColor"/>
                <path d="M2 17L12 22L22 17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                <path d="M2 12L12 17L22 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
              </svg>
            </div>
            <h2 class="chat-title">AI 学习助手</h2>
          </div>
          <el-input
            v-model="inputMessage"
            type="textarea"
            :rows="1"
            :autosize="{ minRows: 1, maxRows: 3 }"
            placeholder="输入您的问题... (按 Enter 发送，Shift + Enter 换行)"
            @keydown.enter.exact.prevent="handleEnter"
            @keydown.shift.enter.exact="handleShiftEnter"
            :disabled="isLoading"
            class="chat-input"
          />
          <el-button
            type="primary"
            :icon="Promotion"
            @click="handleSend"
            :loading="isLoading"
            :disabled="!inputMessage.trim() || isLoading"
            class="send-button"
          >
            {{ isLoading ? '发送中' : '发送' }}
          </el-button>

          <el-button
              type="danger"
              plain
              :icon="Delete"
              @click="handleClearChat"
              :disabled="messages.length === 0"
          >
            清空对话
          </el-button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, nextTick, onMounted, onUnmounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Delete, Promotion } from '@element-plus/icons-vue'
import { getChatRecord, clearChatHistory, deleteChat } from '@/apis/ai.js'
import { useUserStore } from '@/stores/userStore.js'
import avatarDefault from '@/assets/user/empty-avatar.png'
import { formatMessage, escapeHtml } from './messageFormatter.js'

const userStore = useUserStore()
const messages = ref([])
const inputMessage = ref('')
const isLoading = ref(false)
const chatBodyRef = ref(null)
const hoveredMessageIndex = ref(null)
const copiedIndex = ref(null)
const editingMessageId = ref(null)
const editingMessageIndex = ref(null)
const editingContent = ref('')
const hideTimer = ref(null)

const suggestions = [
  '你好，你是谁？',
  '如何使用这个平台学习英语？',
  '如何记忆英语单词？',
  '给我一些英语学习的建议',
  '解释一下过去完成时的用法'
]


// 滚动到底部
const scrollToBottom = () => {
  nextTick(() => {
    if (chatBodyRef.value) {
      chatBodyRef.value.scrollTop = chatBodyRef.value.scrollHeight
    }
  })
}

// 处理 AI文本框 消息悬停
const handleMessageHover = (index) => {
  // 清除之前的隐藏定时器
  if (hideTimer.value) {
    clearTimeout(hideTimer.value)
    hideTimer.value = null
  }
  hoveredMessageIndex.value = index
}

// 处理 AI文本框 消息离开
const handleMessageLeave = () => {
  // 延迟隐藏，给用户时间移动到按钮上
  hideTimer.value = setTimeout(() => {
    hoveredMessageIndex.value = null
    hideTimer.value = null
  }, 500) // 500毫秒延迟
}

// 处理 用户文本框 操作按钮区域悬停（防止鼠标移动到按钮上时隐藏）
const handleActionsHover = () => {
  // 清除隐藏定时器
  if (hideTimer.value) {
    clearTimeout(hideTimer.value)
    hideTimer.value = null
  }
}

// 处理 用户文本框操 作按钮区域离开
const handleActionsLeave = () => {
  // 延迟隐藏
  hideTimer.value = setTimeout(() => {
    hoveredMessageIndex.value = null
    hideTimer.value = null
  }, 500)
}

// 发送消息
const sendMessage = async (question, messageId = null) => {
  if (!question.trim() || isLoading.value) return

  const userMessage = question.trim()
  // 如果没有传入messageId，则从editingMessageId获取（兼容普通发送）
  const editId = messageId !== null ? messageId : editingMessageId.value
  inputMessage.value = ''
  editingMessageId.value = null // 清除编辑状态

  // 添加用户消息
  messages.value.push({
    id: editId,
    role: 'user',
    content: userMessage,
    timestamp: new Date()
  })

  scrollToBottom()

  // 添加AI消息占位符
  const aiMessageIndex = messages.value.length
  messages.value.push({
    role: 'assistant',
    content: '',
    isStreaming: true,
    timestamp: new Date()
  })

  isLoading.value = true
  scrollToBottom()

  // 流式获取AI回复
  try {
    const baseURL = 'http://localhost:8090'
    const token = userStore.userInfo?.accessToken

    // 如果是编辑模式，使用编辑接口
    const url = editId 
      ? `${baseURL}/ai/edit?question=${encodeURIComponent(userMessage)}&id=${editId}`
      : `${baseURL}/ai/chat/stream?question=${encodeURIComponent(userMessage)}`
    
    const response = await fetch(url, {
      method: 'GET',
      headers: {
        'Authorization': token ? `Bearer ${token}` : '',
        'Accept': 'text/event-stream',
        'Cache-Control': 'no-cache'
      },
      credentials: 'include'
    })

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`)
    }

    if (!response.body) {
      throw new Error('Response body is null')
    }

    const reader = response.body.getReader()
    const decoder = new TextDecoder('utf-8')
    let buffer = ''
    let fullContent = ''

    const readStream = () => {
      reader.read().then(({ done, value }) => {
        if (done) {
          // 流结束
          messages.value[aiMessageIndex].isStreaming = false
          isLoading.value = false
          // 确保最终内容被保存
          if (fullContent) {
            messages.value[aiMessageIndex].content = fullContent
          }
          // 流式响应完成后，更新最后两条消息的id和conversationId（用户消息和AI回复）
          updateLastMessagesId()
          scrollToBottom()
          return
        }

        // 解码新数据
        const chunk = decoder.decode(value, { stream: true })
        buffer += chunk
        
        // 处理SSE格式的数据（SSE事件以\n\n分隔）
        let eventEndIndex
        while ((eventEndIndex = buffer.indexOf('\n\n')) !== -1) {
          const eventText = buffer.substring(0, eventEndIndex)
          buffer = buffer.substring(eventEndIndex + 2)
          
          if (!eventText.trim()) continue
          
          const lines = eventText.split('\n')
          let eventData = ''
          let eventName = ''
          
          for (const line of lines) {
            const trimmedLine = line.trim()
            if (!trimmedLine) continue
            
            // 处理 data: 或 data: 开头的行（注意可能有空格也可能没有）
            if (trimmedLine.startsWith('data:')) {
              // 提取data后面的内容，跳过"data:"（5个字符）和可能的空格
              let dataValue = trimmedLine.substring(5)
              // 如果第一个字符是空格，跳过它
              if (dataValue.startsWith(' ')) {
                dataValue = dataValue.substring(1)
              }
              // 确保dataValue不为空且不是"data:"本身
              if (dataValue && !dataValue.startsWith('data:')) {
                // 处理多行data的情况
                eventData = eventData ? eventData + dataValue : dataValue
              }
            } else if (trimmedLine.startsWith('event:')) {
              // 提取event后面的内容
              let eventValue = trimmedLine.substring(6)
              if (eventValue.startsWith(' ')) {
                eventValue = eventValue.substring(1)
              }
              eventName = eventValue.trim()
            } else if (trimmedLine.startsWith('id:') || trimmedLine.startsWith('retry:')) {
              // 忽略id和retry字段
              continue
            } else if (trimmedLine.startsWith(':')) {
              // 忽略注释行
              continue
            } else {
              // 如果没有data:前缀，可能是直接的数据行（兼容某些SSE实现）
              // 但这种情况不应该出现，如果出现可能是格式错误
              if (!eventData) {
                // 只有在确实没有data字段时才使用这行作为数据
                eventData = trimmedLine
              }
            }
          }
          
          // 处理message事件的数据或没有事件名的数据
          if (eventData && eventData !== '[DONE]') {
            if (eventName === 'message' || !eventName) {
              fullContent += eventData
              // 立即更新消息内容，确保触发响应式更新
              if (messages.value[aiMessageIndex]) {
                // 直接更新内容
                messages.value[aiMessageIndex].content = fullContent
                // 调试日志（生产环境可移除）
                if (process.env.NODE_ENV === 'development') {
                  console.log('Stream chunk received:', eventData, 'total length:', fullContent.length)
                }
              }
              // 使用nextTick确保DOM更新后再滚动
              nextTick(() => {
                scrollToBottom()
              })
            }
          }
        }
        
        // 处理缓冲区中剩余的不完整数据
        // 如果buffer中还有数据但没有完整的\n\n分隔，尝试处理完整的行
        if (buffer && !buffer.includes('\n\n')) {
          const lines = buffer.split('\n')
          const remainingLines = []
          
          for (let i = 0; i < lines.length; i++) {
            const line = lines[i].trim()
            if (!line) {
              remainingLines.push('')
              continue
            }
            
            // 处理完整的data:行
            if (line.startsWith('data:')) {
              let dataValue = line.substring(5)
              if (dataValue.startsWith(' ')) {
                dataValue = dataValue.substring(1)
              }
              if (dataValue && dataValue !== '[DONE]') {
                fullContent += dataValue
                if (messages.value[aiMessageIndex]) {
                  messages.value[aiMessageIndex].content = fullContent
                }
                nextTick(() => {
                  scrollToBottom()
                })
              }
              // 这行已处理，不加入remainingLines
            } else if (line.startsWith('event:') || line.startsWith('id:') || line.startsWith('retry:') || line.startsWith(':')) {
              // 忽略这些行
            } else {
              // 其他行保留在buffer中
              remainingLines.push(lines[i])
            }
          }
          
          // 更新buffer，保留未处理的行
          buffer = remainingLines.join('\n')
        }

        // 继续读取
        readStream()
      }).catch(error => {
        console.error('Stream read error:', error)
        ElMessage.error('读取回复时出错：' + error.message)
        messages.value[aiMessageIndex].isStreaming = false
        // 如果有部分内容，保留它
        if (fullContent) {
          messages.value[aiMessageIndex].content = fullContent
          // 即使出错，如果有内容，也尝试更新id
          updateLastMessagesId()
        } else {
          messages.value[aiMessageIndex].content = '抱歉，读取回复时出现错误，请稍后重试。'
        }
        isLoading.value = false
        scrollToBottom()
      })
    }

    readStream()
  } catch (error) {
    console.error('Chat error:', error)
    ElMessage.error('发送消息失败：' + error.message)
    messages.value[aiMessageIndex].isStreaming = false
    messages.value[aiMessageIndex].content = '抱歉，发送消息时出现错误，请稍后重试。'
    isLoading.value = false
  }
}

// 处理发送
const handleSend = () => {
  sendMessage(inputMessage.value)
}

// 处理Enter键
const handleEnter = () => {
  if (!isLoading.value) {
    handleSend()
  }
}

// 处理Shift+Enter
const handleShiftEnter = () => {
  // 允许换行，不做处理
}

// 更新最后两条消息的id和conversationId（用于新发送的消息）
const updateLastMessagesId = async () => {
  try {
    const response = await getChatRecord()
    if (response && response.code === 200 && response.data && Array.isArray(response.data)) {
      const backendMessages = response.data
      // 获取最后两条消息（用户消息和AI回复）
      if (backendMessages.length >= 2) {
        const lastUserMsg = backendMessages[backendMessages.length - 2]
        const lastAiMsg = backendMessages[backendMessages.length - 1]
        
        // 更新前端消息列表中的最后两条消息（通过内容匹配）
        const frontendLength = messages.value.length
        if (frontendLength >= 2) {
          // 找到最后一条用户消息（没有id的）
          for (let i = frontendLength - 2; i >= 0; i--) {
            const msg = messages.value[i]
            if (msg.role === 'user' && !msg.id && msg.content === lastUserMsg.content) {
              msg.id = lastUserMsg.id
              msg.conversationId = lastUserMsg.conversationId
              break
            }
          }
          // 找到最后一条AI消息（没有id的或正在流式的）
          for (let i = frontendLength - 1; i >= 0; i--) {
            const msg = messages.value[i]
            if (msg.role === 'assistant' && (!msg.id || msg.isStreaming === false) && msg.content === lastAiMsg.content) {
              msg.id = lastAiMsg.id
              msg.conversationId = lastAiMsg.conversationId
              break
            }
          }
        }
      }
    }
  } catch (error) {
    console.error('Update messages id error:', error)
    // 更新失败不影响使用，静默处理
  }
}

// 加载历史对话记录
const loadChatHistory = async () => {
  try {
    const response = await getChatRecord()
    // 检查响应格式：R 对象包含 code 和 data
    if (response && response.code === 200 && response.data && Array.isArray(response.data)) {
      // 将后端返回的数据转换为前端需要的格式
      // 后端role: 1=用户, 2=助手，需要转换
      messages.value = response.data.map(msg => ({
        id: msg.id,
        conversationId: msg.conversationId,
        role: msg.role === 1 ? 'user' : (msg.role === 2 ? 'assistant' : 'assistant'),
        content: msg.content || '',
        timestamp: msg.createTime ? new Date(msg.createTime) : new Date()
      }))
      // 加载完成后滚动到底部
      scrollToBottom()
    } else if (response && Array.isArray(response)) {
      // 兼容直接返回数组的情况
      messages.value = response.map(msg => ({
        id: msg.id,
        conversationId: msg.conversationId,
        role: msg.role === 1 ? 'user' : (msg.role === 2 ? 'assistant' : 'assistant'),
        content: msg.content || '',
        timestamp: msg.createTime ? new Date(msg.createTime) : new Date()
      }))
      scrollToBottom()
    }
  } catch (error) {
    console.error('Load chat history error:', error)
    // 加载失败不显示错误提示，因为可能是首次使用没有历史记录
  }
}

// 开始编辑消息
const handleStartEdit = async (message, index) => {
  if (!message.id) {
    ElMessage.warning('该消息无法编辑')
    return
  }
  
  editingMessageIndex.value = index
  editingContent.value = message.content
  editingMessageId.value = message.id
  
  // 聚焦到输入框
  await nextTick()
  setTimeout(() => {
    const editInputs = document.querySelectorAll('.message-edit-input textarea')
    if (editInputs.length > 0) {
      const textarea = editInputs[editInputs.length - 1] // 获取最后一个（当前编辑的）
      if (textarea) {
        textarea.focus()
        textarea.setSelectionRange(textarea.value.length, textarea.value.length)
      }
    }
  }, 100)
}

// 保存编辑
const handleSaveEdit = async (index) => {
  const newContent = editingContent.value.trim()
  if (!newContent) {
    ElMessage.warning('消息内容不能为空')
    return
  }
  
  const message = messages.value[index]
  if (!message.id) {
    ElMessage.warning('该消息无法编辑')
    return
  }
  
  // 如果内容没有变化，直接取消编辑
  if (newContent === message.content) {
    handleCancelEdit()
    return
  }
  
  // 删除该消息及其之后的所有消息
  messages.value = messages.value.slice(0, index)
  
  // 保存messageId用于发送
  const messageId = editingMessageId.value
  
  // 清除编辑状态
  editingMessageIndex.value = null
  editingContent.value = ''
  editingMessageId.value = null
  
  // 发送编辑后的消息，传入messageId确保调用编辑接口
  await sendMessage(newContent, messageId)
}

// 取消编辑
const handleCancelEdit = () => {
  editingMessageIndex.value = null
  editingContent.value = ''
  editingMessageId.value = null
}

// 删除消息
const handleDeleteMessage = async (message, index) => {
  if (!message.id) {
    ElMessage.warning('该消息无法删除')
    return
  }

  try {
    await ElMessageBox.confirm(
      '删除此消息将同时删除该消息及其对应的AI回复，确定要继续吗？',
      '提示',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }
    )

    // 调用删除接口
    await deleteChat(message.id)
    
    // 从消息列表中删除该消息及其对应的AI回复
    // 找到该消息对应的对话对（用户消息和AI回复）
    const conversationId = message.conversationId
    if (conversationId) {
      // 如果有conversationId，删除同一对话的所有消息
      messages.value = messages.value.filter(msg => msg.conversationId !== conversationId)
    } else {
      // 否则只删除当前消息和下一个AI回复
      if (messages.value[index + 1] && messages.value[index + 1].role === 'assistant') {
        messages.value.splice(index, 2)
      } else {
        messages.value.splice(index, 1)
      }
    }
    
    ElMessage.success('消息已删除')
    scrollToBottom()
  } catch (error) {
    console.error('Delete message error:', error)
    if (error !== 'cancel') {
      ElMessage.error('删除消息失败')
    }
  }
}

// 清空对话
const handleClearChat = async () => {
  try {
    await ElMessageBox.confirm(
      '确定要清空所有对话记录吗？此操作不可恢复。',
      '提示',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }
    )

    try {
      await clearChatHistory()
      messages.value = []
      ElMessage.success('对话记录已清空')
    } catch (error) {
      console.error('Clear chat error:', error)
      ElMessage.error('清空对话失败')
    }
  } catch {
    // 用户取消
  }
}

// 复制消息内容
const copyMessage = async (content, index) => {
  try {
    // 创建一个临时div来提取纯文本
    const tempDiv = document.createElement('div')
    tempDiv.innerHTML = formatMessage(content)
    
    // 获取纯文本内容，保留换行和格式
    let textContent = tempDiv.textContent || tempDiv.innerText || ''
    
    // 清理多余的空白字符，但保留换行
    textContent = textContent
      .replace(/\n{3,}/g, '\n\n') // 多个换行合并为两个
      .replace(/[ \t]+/g, ' ') // 多个空格合并为一个
      .trim()
    
    await navigator.clipboard.writeText(textContent)
    copiedIndex.value = index
    ElMessage.success('已复制到剪贴板')
    
    // 2秒后重置复制状态
    setTimeout(() => {
      if (copiedIndex.value === index) {
        copiedIndex.value = null
      }
    }, 2000)
  } catch (error) {
    console.error('复制失败:', error)
    // 降级方案：使用传统方法
    try {
      const tempDiv = document.createElement('div')
      tempDiv.innerHTML = formatMessage(content)
      let textContent = tempDiv.textContent || tempDiv.innerText || ''
      textContent = textContent.replace(/\n{3,}/g, '\n\n').replace(/[ \t]+/g, ' ').trim()
      
      const textarea = document.createElement('textarea')
      textarea.value = textContent
      textarea.style.position = 'fixed'
      textarea.style.opacity = '0'
      textarea.style.left = '-9999px'
      document.body.appendChild(textarea)
      textarea.select()
      textarea.setSelectionRange(0, 99999) // 兼容移动设备
      
      const successful = document.execCommand('copy')
      document.body.removeChild(textarea)
      
      if (successful) {
        copiedIndex.value = index
        ElMessage.success('已复制到剪贴板')
        setTimeout(() => {
          if (copiedIndex.value === index) {
            copiedIndex.value = null
          }
        }, 2000)
      } else {
        ElMessage.error('复制失败，请手动选择文本复制')
      }
    } catch (err) {
      console.error('降级复制也失败:', err)
      ElMessage.error('复制失败，请手动选择文本复制')
    }
  }
}

// 处理代码块复制按钮点击
const handleCodeCopy = (event) => {
  const target = event.target
  if (target.classList.contains('code-copy-btn')) {
    const encodedCode = target.getAttribute('data-code')
    if (encodedCode) {
      const code = decodeURIComponent(encodedCode)
      navigator.clipboard.writeText(code).then(() => {
        const originalText = target.textContent
        target.textContent = '已复制'
        target.classList.add('copied')
        setTimeout(() => {
          target.textContent = originalText
          target.classList.remove('copied')
        }, 2000)
      }).catch(err => {
        console.error('复制失败:', err)
        ElMessage.error('复制失败，请手动选择文本复制')
      })
    }
  }
}

// 组件挂载时加载历史记录并滚动到底部
onMounted(async () => {
  await loadChatHistory()
  scrollToBottom()
  
  // 添加代码块复制按钮的事件委托
  const chatBody = chatBodyRef.value
  if (chatBody) {
    chatBody.addEventListener('click', handleCodeCopy)
  }
})

// 组件卸载时移除事件监听和清理定时器
onUnmounted(() => {
  const chatBody = chatBodyRef.value
  if (chatBody) {
    chatBody.removeEventListener('click', handleCodeCopy)
  }
  // 清理隐藏定时器
  if (hideTimer.value) {
    clearTimeout(hideTimer.value)
    hideTimer.value = null
  }
})
</script>

<style scoped>
.ai-chat-container {
  margin-top: 15px;
  display: flex;
  flex-direction: column;
  height: calc(100vh - 80px);
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  position: relative;
  overflow: hidden;
}

.ai-chat-container::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: 
    radial-gradient(circle at 20% 50%, rgba(255, 255, 255, 0.1) 0%, transparent 50%),
    radial-gradient(circle at 80% 80%, rgba(255, 255, 255, 0.1) 0%, transparent 50%);
  pointer-events: none;
}

.chat-header {
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(10px);
  padding: 0.5rem 1.5rem;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  z-index: 10;
  position: relative;
  flex-shrink: 0;
}



.chat-bottom-left {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-right: 100px;
}

.ai-avatar {
  width: 32px;
  height: 32px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
  flex-shrink: 0;
}

.ai-avatar svg {
  width: 20px;
  height: 20px;
}

.chat-title {
  margin: 0;
  font-size: 1.1rem;
  font-weight: 700;
  color: #2d3748;
  white-space: nowrap;
}

.chat-body {
  flex: 1;
  overflow-y: auto;
  padding: 1.5rem;
  position: relative;
  z-index: 1;
  min-height: 0;
}

.chat-body::-webkit-scrollbar {
  width: 8px;
}

.chat-body::-webkit-scrollbar-track {
  background: rgba(255, 255, 255, 0.1);
  border-radius: 4px;
}

.chat-body::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.3);
  border-radius: 4px;
}

.chat-body::-webkit-scrollbar-thumb:hover {
  background: rgba(255, 255, 255, 0.5);
}

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: white;
  text-align: center;
  padding: 2rem;
}

.empty-icon {
  font-size: 5rem;
  margin-bottom: 1.5rem;
  animation: float 3s ease-in-out infinite;
}

@keyframes float {
  0%, 100% {
    transform: translateY(0px);
  }
  50% {
    transform: translateY(-20px);
  }
}

.empty-state h3 {
  font-size: 1.75rem;
  margin: 0 0 0.5rem 0;
  font-weight: 600;
}

.empty-state p {
  font-size: 1.125rem;
  margin: 0 0 2rem 0;
  opacity: 0.9;
}

.suggestions {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  justify-content: center;
  max-width: 600px;
}

.suggestion-item {
  padding: 0.75rem 1.5rem;
  background: rgba(255, 255, 255, 0.2);
  backdrop-filter: blur(10px);
  border-radius: 25px;
  cursor: pointer;
  transition: all 0.3s ease;
  border: 1px solid rgba(255, 255, 255, 0.3);
  font-size: 0.9rem;
}

.suggestion-item:hover {
  background: rgba(255, 255, 255, 0.3);
  transform: translateY(-2px);
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
}

.messages-list {
  max-width: 1200px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.message-item {
  display: flex;
  gap: 1rem;
  animation: slideIn 0.3s ease-out;
}

@keyframes slideIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.message-item.user {
  flex-direction: row-reverse;
}

.message-avatar {
  flex-shrink: 0;
}

.user-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid rgba(255, 255, 255, 0.3);
  box-shadow: 0 4px 15px rgba(245, 87, 108, 0.4);
  background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
}

.ai-avatar-small {
  width: 40px;
  height: 40px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
}

.ai-avatar-small svg {
  width: 22px;
  height: 22px;
}

.message-content {
  flex: 1;
  max-width: 70%;
  min-width: 200px;
  position: relative;
  margin-bottom: 3rem;
}

.message-item.user .message-content {
  margin-bottom: 3rem;
}

.message-text-wrapper {
  position: relative;
  user-select: text;
  -webkit-user-select: text;
  -moz-user-select: text;
  -ms-user-select: text;
}

.copy-button {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.2s ease;
  padding: 0;
  z-index: 10;
  color: #4a5568;
}

.copy-button:hover {
  background: rgba(255, 255, 255, 1);
  border-color: rgba(102, 126, 234, 0.3);
  color: #667eea;
  transform: scale(1.05);
}

.copy-button:active {
  transform: scale(0.95);
}

.copy-button svg {
  width: 16px;
  height: 16px;
}

.message-item.user .message-text-wrapper .copy-button {
  right: auto;
  left: 0.5rem;
}

/* 用户消息操作按钮组 */
.message-actions {
  position: absolute;
  bottom: -3rem;
  right: 0;
  display: flex;
  gap: 0.5rem;
  align-items: center;
  z-index: 10;
  animation: fadeInUp 0.3s ease-out;
  padding: 0.25rem;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(12px);
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 用户消息的按钮保持在右下角，不需要特殊处理 */

/* 操作按钮通用样式 */
.action-btn {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(12px);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
  padding: 0;
  color: #4a5568;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  position: relative;
  overflow: hidden;
}

.action-btn::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  border-radius: 50%;
  background: rgba(102, 126, 234, 0.1);
  transform: translate(-50%, -50%);
  transition: width 0.3s ease, height 0.3s ease;
}

.action-btn:hover::before {
  width: 100%;
  height: 100%;
}

.action-btn:hover {
  transform: translateY(-2px) scale(1.05);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  border-color: rgba(102, 126, 234, 0.3);
}

.action-btn:active {
  transform: translateY(0) scale(0.98);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
}

.action-btn svg {
  width: 16px;
  height: 16px;
  position: relative;
  z-index: 1;
  transition: all 0.2s ease;
}

/* 复制按钮样式 */
.copy-btn {
  color: #667eea;
}

.copy-btn:hover {
  background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%);
  color: #667eea;
}

.copy-btn:active {
  color: #764ba2;
}

/* 编辑按钮样式 */
.edit-btn {
  color: #10b981;
}

.edit-btn:hover {
  background: linear-gradient(135deg, rgba(16, 185, 129, 0.1) 0%, rgba(5, 150, 105, 0.1) 100%);
  color: #10b981;
  border-color: rgba(16, 185, 129, 0.3);
}

.edit-btn:active {
  color: #059669;
}

/* 删除按钮样式 */
.delete-btn {
  color: #ef4444;
}

.delete-btn:hover {
  background: linear-gradient(135deg, rgba(239, 68, 68, 0.1) 0%, rgba(220, 38, 38, 0.1) 100%);
  color: #ef4444;
  border-color: rgba(239, 68, 68, 0.3);
}

.delete-btn:active {
  color: #dc2626;
}

/* 编辑模式样式 */
.message-edit-wrapper {
  position: relative;
  width: 100%;
}

.message-edit-input {
  width: 100%;
}

.message-edit-input :deep(.el-textarea__inner) {
  border-radius: 12px;
  border: 2px solid #667eea;
  padding: 0.75rem 1rem;
  font-size: 0.95rem;
  resize: none;
  transition: all 0.3s ease;
  background: rgba(255, 255, 255, 0.98);
  box-shadow: 0 4px 12px rgba(102, 126, 234, 0.15);
}

.message-edit-input :deep(.el-textarea__inner):focus {
  border-color: #764ba2;
  box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.2);
}

.edit-actions {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.75rem;
  justify-content: flex-end;
}

.edit-save-btn,
.edit-cancel-btn {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 1rem;
  border-radius: 8px;
  font-size: 0.875rem;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
  border: none;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.edit-save-btn {
  background: linear-gradient(135deg, #10b981 0%, #059669 100%);
  color: white;
}

.edit-save-btn:hover {
  background: linear-gradient(135deg, #059669 0%, #047857 100%);
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3);
}

.edit-save-btn:active {
  transform: translateY(0);
  box-shadow: 0 2px 6px rgba(16, 185, 129, 0.2);
}

.edit-save-btn svg {
  width: 16px;
  height: 16px;
}

.edit-cancel-btn {
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(10px);
  color: #4a5568;
  border: 1px solid rgba(0, 0, 0, 0.1);
}

.edit-cancel-btn:hover {
  background: rgba(255, 255, 255, 1);
  color: #2d3748;
  border-color: rgba(0, 0, 0, 0.15);
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.edit-cancel-btn:active {
  transform: translateY(0);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
}

.edit-cancel-btn svg {
  width: 16px;
  height: 16px;
}

.message-item.user .message-content {
  display: flex;
  justify-content: flex-end;
}

.message-text {
  padding: 1rem 1.25rem;
  border-radius: 18px;
  line-height: 1.6;
  word-wrap: break-word;
  font-size: 0.95rem;
  animation: typewriter 0.1s;
  user-select: text;
  -webkit-user-select: text;
  -moz-user-select: text;
  -ms-user-select: text;
}

.message-item.user .message-text {
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(10px);
  color: #2d3748;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
  border-bottom-right-radius: 4px;
}

.message-item.assistant .message-text {
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(10px);
  color: #2d3748;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
  border-bottom-left-radius: 4px;
}

.message-text code {
  background: linear-gradient(135deg, rgba(102, 126, 234, 0.15) 0%, rgba(118, 75, 162, 0.15) 100%);
  padding: 0.2rem 0.5rem;
  border-radius: 6px;
  font-family: 'Courier New', 'Consolas', 'Monaco', monospace;
  font-size: 0.9em;
  color: #667eea;
  font-weight: 500;
  border: 1px solid rgba(102, 126, 234, 0.2);
}

.message-text pre {
  background: rgba(0, 0, 0, 0.05);
  padding: 1rem;
  border-radius: 8px;
  overflow-x: auto;
  margin: 0.5rem 0;
}

.message-text pre code {
  background: transparent;
  padding: 0;
  font-size: 0.9em;
  line-height: 1.5;
  color: inherit;
  border: none;
}

/* 代码块包装器 */
.code-block-wrapper {
  margin: 1rem 0;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  background: #1e1e1e;
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.code-block-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.75rem 1rem;
  background: rgba(0, 0, 0, 0.3);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.code-lang {
  font-size: 0.85rem;
  color: rgba(255, 255, 255, 0.7);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.code-copy-btn {
  background: rgba(102, 126, 234, 0.2);
  border: 1px solid rgba(102, 126, 234, 0.3);
  color: rgba(255, 255, 255, 0.9);
  padding: 0.4rem 0.8rem;
  border-radius: 6px;
  font-size: 0.8rem;
  cursor: pointer;
  transition: all 0.2s ease;
  font-weight: 500;
}

.code-copy-btn:hover {
  background: rgba(102, 126, 234, 0.4);
  border-color: rgba(102, 126, 234, 0.5);
  transform: translateY(-1px);
}

.code-copy-btn:active {
  transform: translateY(0);
}

.code-copy-btn.copied {
  background: rgba(34, 197, 94, 0.3) !important;
  border-color: rgba(34, 197, 94, 0.5) !important;
  color: #22c55e !important;
}

.code-block {
  margin: 0;
  padding: 1rem;
  background: #1e1e1e;
  color: #d4d4d4;
  font-family: 'Courier New', 'Consolas', 'Monaco', monospace;
  font-size: 0.9em;
  line-height: 1.6;
  overflow-x: auto;
}

.code-block code {
  background: transparent;
  padding: 0;
  color: inherit;
  border: none;
  font-size: inherit;
}

/* 标题样式 */
.markdown-h1,
.message-text h1 {
  margin: 1.5rem 0 1rem 0;
  font-weight: 800;
  line-height: 1.3;
  font-size: 1.75rem;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  position: relative;
  padding-bottom: 0.5rem;
}

.markdown-h1::after,
.message-text h1::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  width: 60px;
  height: 3px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 2px;
}

.markdown-h2,
.message-text h2 {
  margin: 1.25rem 0 0.75rem 0;
  font-weight: 700;
  line-height: 1.3;
  font-size: 1.4rem;
  color: #2d3748;
  position: relative;
  padding-left: 0.75rem;
}

.markdown-h2::before,
.message-text h2::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.2em;
  bottom: 0.2em;
  width: 4px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 2px;
}

.markdown-h3,
.message-text h3 {
  margin: 1rem 0 0.5rem 0;
  font-weight: 700;
  line-height: 1.4;
  font-size: 1.15rem;
  color: #4a5568;
  position: relative;
}

.markdown-strong,
.message-text strong {
  font-weight: 700;
  color: #2d3748;
  background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%);
  padding: 0.1rem 0.3rem;
  border-radius: 4px;
}

.markdown-em,
.message-text em {
  font-style: italic;
  color: #4a5568;
  font-weight: 500;
}

.markdown-del,
.message-text del {
  text-decoration: line-through;
  color: #718096;
  opacity: 0.7;
}

/* 列表样式 */
.markdown-ul,
.message-text ul {
  margin: 0.75rem 0;
  padding-left: 1.5rem;
  list-style: none;
}

.markdown-ul .markdown-li,
.message-text ul li {
  position: relative;
  padding-left: 1.5rem;
  margin: 0.5rem 0;
  line-height: 1.7;
}

.markdown-ul .markdown-li::before,
.message-text ul li::before {
  content: '▸';
  position: absolute;
  left: 0;
  color: #667eea;
  font-weight: bold;
  font-size: 1.2em;
}

.markdown-ol,
.message-text ol {
  margin: 0.75rem 0;
  padding-left: 1.5rem;
  counter-reset: list-counter;
}

.markdown-ol .markdown-li,
.message-text ol li {
  counter-increment: list-counter;
  position: relative;
  padding-left: 1.5rem;
  margin: 0.5rem 0;
  line-height: 1.7;
  list-style: none;
}

.markdown-ol .markdown-li::before,
.message-text ol li::before {
  content: counter(list-counter) '.';
  position: absolute;
  left: 0;
  color: #667eea;
  font-weight: 700;
  min-width: 1.5rem;
}

/* 链接样式 */
.markdown-link,
.message-text a {
  color: #667eea;
  text-decoration: none;
  border-bottom: 2px solid rgba(102, 126, 234, 0.3);
  transition: all 0.2s ease;
  font-weight: 500;
  padding: 0 0.1rem;
  position: relative;
}

.markdown-link:hover,
.message-text a:hover {
  color: #764ba2;
  border-bottom-color: #764ba2;
  background: rgba(102, 126, 234, 0.05);
  border-radius: 3px;
}

/* 段落样式 */
.markdown-p,
.message-text p {
  margin: 0.75rem 0;
  line-height: 1.8;
  color: #2d3748;
  text-align: justify;
}

.markdown-p:first-child,
.message-text p:first-child {
  margin-top: 0;
}

.markdown-p:last-child,
.message-text p:last-child {
  margin-bottom: 0;
}

/* 水平线样式 */
.message-text hr {
  border: none;
  height: 2px;
  background: linear-gradient(90deg, transparent 0%, rgba(102, 126, 234, 0.3) 50%, transparent 100%);
  margin: 3rem 0 2rem 0;
  position: relative;
}

.message-text hr::before {
  content: '◆';
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  background: rgba(255, 255, 255, 0.95);
  padding: 0 0.5rem;
  color: #667eea;
  font-size: 0.8rem;
}

/* 引用块样式 */
.markdown-blockquote,
.message-text blockquote {
  margin: 1rem 0;
  padding: 1rem 1.25rem;
  padding-left: 1.5rem;
  background: linear-gradient(135deg, rgba(102, 126, 234, 0.08) 0%, rgba(118, 75, 162, 0.08) 100%);
  border-left: 4px solid #667eea;
  border-radius: 8px;
  position: relative;
  font-style: italic;
  color: #4a5568;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}

.markdown-blockquote::before,
.message-text blockquote::before {
  content: '"';
  position: absolute;
  left: 0.5rem;
  top: 0.5rem;
  font-size: 2rem;
  color: #667eea;
  opacity: 0.3;
  font-family: Georgia, serif;
}

.markdown-blockquote p,
.message-text blockquote p {
  margin: 0.5rem 0;
}

.markdown-blockquote p:first-child,
.message-text blockquote p:first-child {
  margin-top: 0;
}

.markdown-blockquote p:last-child,
.message-text blockquote p:last-child {
  margin-bottom: 0;
}

/* 任务列表样式 */
.task-item {
  display: flex;
  align-items: flex-start;
  margin: 0.5rem 0;
  padding: 0.5rem;
  border-radius: 6px;
  transition: background 0.2s ease;
}

.task-item:hover {
  background: rgba(102, 126, 234, 0.05);
}

.task-item input[type="checkbox"] {
  margin-right: 0.75rem;
  margin-top: 0.2rem;
  width: 18px;
  height: 18px;
  cursor: pointer;
  accent-color: #667eea;
  flex-shrink: 0;
}

.task-content {
  flex: 1;
  line-height: 1.6;
  color: #2d3748;
}

.task-item input[type="checkbox"]:checked + .task-content {
  text-decoration: line-through;
  color: #718096;
  opacity: 0.7;
}

.typing-indicator {
  display: flex;
  gap: 4px;
  padding: 0.5rem 0;
  margin-left: 1.25rem;
}

.typing-indicator span {
  width: 8px;
  height: 8px;
  background: white;
  border-radius: 50%;
  animation: typing 1.4s infinite ease-in-out;
}

.typing-indicator span:nth-child(1) {
  animation-delay: -0.32s;
}

.typing-indicator span:nth-child(2) {
  animation-delay: -0.16s;
}

@keyframes typing {
  0%, 80%, 100% {
    transform: scale(0.8);
    opacity: 0.5;
  }
  40% {
    transform: scale(1);
    opacity: 1;
  }
}

.chat-bottom {
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(10px);
  padding: 0.75rem 1.5rem;
  box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
  z-index: 10;
  position: relative;
  flex-shrink: 0;
}

.bottom-wrapper {
  max-width: 1200px;
  margin: 10px auto 0;
}

.bottom-row {
  display: flex;
  gap: 0.75rem;
  align-items: flex-end;
}

.chat-input {
  flex: 1;
  margin-bottom: -4px;
}

.chat-input :deep(.el-textarea__inner) {
  border-radius: 12px;
  border: 2px solid #e2e8f0;
  padding: 0.75rem 1rem;
  font-size: 0.95rem;
  resize: none;
  transition: all 0.3s ease;
}

.chat-input :deep(.el-textarea__inner):focus {
  border-color: #667eea;
  box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}

.send-button {
  padding: 0.75rem 1.5rem;
  border-radius: 8px;
  font-weight: 600;
  box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
  transition: all 0.3s ease;
  white-space: nowrap;
  height: fit-content;
  margin-bottom: 0;
}

.send-button:hover:not(:disabled) {
  transform: translateY(-2px);
  box-shadow: 0 6px 20px rgba(102, 126, 234, 0.5);
}

.send-button:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

@media (max-width: 768px) {
  .chat-header {
    padding: 1rem;
  }

  .header-content {
    flex-direction: column;
    gap: 1rem;
    align-items: flex-start;
  }

  .chat-body {
    padding: 1rem;
  }

  .message-content {
    max-width: 85%;
  }

  .chat-bottom {
    padding: 0.75rem 1rem;
  }

  .bottom-row {
    flex-direction: column;
    gap: 0.5rem;
  }

  .send-button {
    width: 100%;
  }
}
</style>

